﻿using System.Diagnostics;

namespace UPKAndUDKUnpackTools.Tools;

/// <summary>
/// 负责从 UDK 文件中导出模型的类。
/// </summary>
public static class UdkExporter
{
    private static int _failedFileCount;
    private static readonly List<string> FailedFilesList = [];
    private static int _successFileCount;
    private static int pv;
    public static event Action<int> pValueOnUpdated;

    /// <summary>
    /// 导出 UDK 文件中的模型。
    /// </summary>
    /// <param name="directory">UDK 文件所在目录。</param>
    /// <param name="finalOutputDir">最终输出目录。</param>
    public static void ExportModelsForUdkFiles(string directory, string finalOutputDir)
    {
        var files = Directory.EnumerateFiles(directory, "*.udk", SearchOption.AllDirectories);

        foreach (var filePath in files)
        {
            pv++;
            Console.WriteLine($"正在处理文件: {filePath}");
            ExportModelFile(filePath, finalOutputDir);
            pValueOnUpdated?.Invoke(pv);
        }
    }

    
    private static void ExportModelFile(string filePath, string outputDir)
    {
        var lightmap = Form1.noLighting? "-nolightmap" : "";
        var sounds = Form1.sounds? "-sounds" : "";
        try
        {
            var uModels = new ProcessStartInfo
            {
                FileName = "umodel64",
                Arguments = $"-export -game=gunsl {lightmap} {sounds} -lods -nooverwrite -out=\"{outputDir}\" \"{filePath}\"",
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };
            using var process = Process.Start(uModels);
            if (process == null) return;
            Console.ForegroundColor = ConsoleColor.DarkCyan;
            process.OutputDataReceived += (_, args) => Console.WriteLine(args.Data);
            process.ErrorDataReceived += (_, args) => Console.WriteLine(args.Data);
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
            var exited = process.WaitForExit(60000);
            if (!exited)
            {
                process.Kill();
                Console.WriteLine("进程超时被终止");
            }
            else
            {
                if (process.ExitCode == 0)
                {
                    _successFileCount++;
                    Console.WriteLine($"成功导出: {GetSubstringFromRight(filePath)}");
                }
                else
                {
                    _failedFileCount++;
                    Console.WriteLine($"导出失败: {GetSubstringFromRight(filePath)}");
                    FailedFilesList.Add(filePath);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"导出 {GetSubstringFromRight(filePath)} 发生错误: {e.Message}");
        }
    }

    /// <summary>
    /// 输出处理文件的状态信息，并根据需要重新处理失败的文件。
    /// </summary>
    public static void GetStatus()
    {
        MessageBox.Show($"已成功解锁导出 {_successFileCount} 个 udk 文件，有 {_failedFileCount} 个导出失败。", "导出完成", MessageBoxButtons.OK,MessageBoxIcon.Information);
        if (_failedFileCount > 0)
        {
            Console.WriteLine("============失败 udk 文件列表============");
            FailedFilesList.ForEach(Console.WriteLine);
            Console.WriteLine("\n以上文件导出失败，即将进行第二次处理。。。。。");
            Parallel.ForEach(FailedFilesList, UdkProcessor.ErrFileHandle);

            var path = DirectoryManager.CreateFolder("Maps");
            ExportModelsForUdkFiles("unlockedUdk", path);
        }

        _successFileCount = 0;
        _failedFileCount = 0;
        pv = 0;
    }
    public static string GetSubstringFromRight(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return string.Empty;
        }
        // 找到最后一个 '/' 或 '\' 的位置
        var lastIndex = input.LastIndexOfAny(['/', '\\']);

        // 如果没有找到，返回整个字符串
        return lastIndex == -1 ? input :
            // 从最后一个 '/' 或 '\' 之后开始取子字符串
            input[(lastIndex + 1)..];
    }

}